package com.lin.generate.config;

import com.lin.generate.common.base.R;
import com.lin.generate.common.enums.SystemEnums;
import com.lin.generate.common.exception.BaseException;
import com.lin.generate.common.vo.response.ArgumentsInvalidResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.util.ArrayList;
import java.util.List;

/**
 * 全局异常处理器
 *
 * @Author: lin.zhao@pinlandata.com
 * @Date: 2021/10/7 22:43
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    public R httpRequestMethodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException e) {
        log.error("http请求的方法不正确:【{}】", e.getMessage(), e);
        return R.fail(SystemEnums.REQUEST_METHOD_NOT_VALID, null);
    }

    @ResponseBody
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public R httpMessageNotReadableExceptionHandler(HttpMessageNotReadableException e) {
        log.error("http请求参数格式不正确:【{}】", e.getMessage(), e);
        return R.fail(SystemEnums.PARAMETER_VERIFICATION_FAILED, null);
    }

    @ResponseBody
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public R handleArgumentException(MethodArgumentTypeMismatchException e) {
        log.error("pinlan-exception:【{}】", e.getMessage(), e);
        return R.fail(SystemEnums.REQUEST_METHOD_NOT_VALID, null);
    }

    @ResponseBody
    @ExceptionHandler(BadSqlGrammarException.class)
    public R handleException(BadSqlGrammarException e) {
        log.error("pinlan-exception:【{}】", e.getMessage(), e);
        //不对用户界面返回sql报错信息
        return R.fail(SystemEnums.SQL_BAD, null);
    }

    @ResponseBody
    @ExceptionHandler(DataIntegrityViolationException.class)
    public R handleSqlException(DataIntegrityViolationException e) {
        log.error("pinlan-exception:【{}】", e.getMessage(), e);
        //不对用户界面返回sql报错信息
        return R.fail(SystemEnums.SQL_BAD.getCode(), SystemEnums.FAIL.getMsg(), null);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public R methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        List<ArgumentsInvalidResponse> argumentsInvalidResponseBeanList = new ArrayList<>();
        StringBuilder stringBuilder = new StringBuilder();
        for (FieldError error : e.getBindingResult().getFieldErrors()) {
            ArgumentsInvalidResponse bean = new ArgumentsInvalidResponse();
            bean.setArgumentName(error.getField());
            bean.setExceptionMsg(error.getDefaultMessage());

            argumentsInvalidResponseBeanList.add(bean);
            stringBuilder.append("、");
            stringBuilder.append(error.getDefaultMessage());
        }
        log.error("pinlan-exception:【{}】", argumentsInvalidResponseBeanList);
        return new R(SystemEnums.PARAMETER_VERIFICATION_FAILED.getCode(), stringBuilder.substring(1));
    }

    @ExceptionHandler(BaseException.class)
    @ResponseBody
    public R methodArgumentNotValidExceptionHandler(BaseException e) {
        log.error("pinlan-exception:【{}】", e.getMessage(), e);
        return R.fail(e.getError(), null);
    }
}
